﻿
&НаСервере
Процедура ПолучитьДанныеОтметки(ОтметкаДаты, ТекстОтметки)
	ОтметкаДаты = Константы.ОтметкаНаФотоснимкеДата.Получить();
	ТекстОтметки = Константы.ОтметкаНаФотоснимкеТекст.Получить();
КонецПроцедуры

//////////////////////////////////////////////////////////////////////////////// 
// ОБРАБОТЧИКИ СОБЫТИЙ 
// 

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	Если Параметры.Ключ.Пустая() И НЕ Параметры.ЗначениеКопирования.Пустая() Тогда
		// при копировании очищаем имя файла, чтобы не возникало иллюзии, что содержимое файла тоже скопируется
		Объект.ИмяФайла = "";
	КонецЕсли;
#Если НЕ МобильныйАвтономныйСервер Тогда
	ПутьКРабочемуКаталогу = РаботаСХранилищемОбщихНастроек.ПолучитьРабочийКаталог();
#Иначе
	ПутьКРабочемуКаталогу = КаталогВременныхФайлов();
#КонецЕсли
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)

#Если НЕ МобильныйКлиент Тогда
	
	Элементы.СделатьИЗаписать.Видимость = Ложь;
	Элементы.СделатьВидеозаписьИЗаписать.Видимость = Ложь;
	Элементы.СделатьФотоснимокИЗаписать.Видимость = Ложь;
	Элементы.ДобавитьСохраненноеАудиоИЗаписать.Видимость = Ложь;
	Элементы.ДобавитьСохраненноеВидеоИЗаписать.Видимость = Ложь;
	Элементы.ДобавитьСохраненноеФотоИЗаписать.Видимость = Ложь;
	
#Иначе
	
	Если ТолькоПросмотр = Ложь Тогда
		Элементы.СделатьИЗаписать.Доступность = СредстваМультимедиа.ПоддерживаетсяАудиозапись();
		Элементы.СделатьВидеозаписьИЗаписать.Доступность = СредстваМультимедиа.ПоддерживаетсяВидеозапись();
		Элементы.СделатьФотоснимокИЗаписать.Доступность = СредстваМультимедиа.ПоддерживаетсяФотоснимок();
		Элементы.ДобавитьСохраненноеАудиоИЗаписать.Доступность = Истина;
		Элементы.ДобавитьСохраненноеВидеоИЗаписать.Доступность = Истина;
		Элементы.ДобавитьСохраненноеФотоИЗаписать.Доступность = Истина;
	Иначе
		Элементы.СделатьИЗаписать.Доступность = Ложь;
		Элементы.СделатьВидеозаписьИЗаписать.Доступность = Ложь;
		Элементы.СделатьФотоснимокИЗаписать.Доступность = Ложь;
		Элементы.ДобавитьСохраненноеАудиоИЗаписать.Доступность = Ложь;
		Элементы.ДобавитьСохраненноеВидеоИЗаписать.Доступность = Ложь;
		Элементы.ДобавитьСохраненноеФотоИЗаписать.Доступность = Ложь;
	КонецЕсли;
	
#КонецЕсли

КонецПроцедуры

&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
	Если Объект.ИмяФайла = "" Тогда
		ВыполнитьПриОтказеОтЗаписи();
		Отказ = Истина;
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Асинх Процедура ВыполнитьПриОтказеОтЗаписи()
	Ждать ПредупреждениеАсинх("Не выбран файл!");
КонецПроцедуры

&НаКлиенте
Процедура ПередПомещениемФайла(ПомещаемыйФайл, ОтказОтПомещенияФайла, ДопПараметры) Экспорт 
	ИндикаторПрогресса = 0;
#Если МобильныйКлиент Тогда
	Элементы.ИндикаторПрогресса.Заголовок = ПомещаемыйФайл.Файл.ПолучитьПредставлениеФайлаБиблиотекиМобильногоУстройства();
#Иначе
	Элементы.ИндикаторПрогресса.Заголовок = ПомещаемыйФайл.Имя;
#КонецЕсли  
	Элементы.ИндикаторПрогресса.Видимость = Истина;
	Элементы.СообщениеОбОшибке.Видимость = Ложь;
КонецПроцедуры

&НаКлиенте
Процедура ХодПомещенияФайла(ПомещаемыйФайл, Помещено, ОтказОтПомещенияФайла, ДопПараметры) Экспорт	
	ИндикаторПрогресса = Помещено;                                	
КонецПроцедуры

&НаКлиенте
Процедура ВыбратьФайлСДискаИЗаписать(Команда)
	ЗапуститьВыборФайлСДискаИЗапись();
КонецПроцедуры

&НаКлиенте
Асинх Процедура ЗапуститьВыборФайлСДискаИЗапись()
	Если Не ЗначениеЗаполнено(Объект.Владелец) Тогда
		Ждать ПредупреждениеАсинх(НСтр("ru='Не заполнен владелец хранимого файла'", "ru"));
		Возврат;
	КонецЕсли;
	ОХодеПомещенияФайла = Новый ОписаниеОповещения("ХодПомещенияФайла", ЭтотОбъект);
	ПередПомещениемФайла = Новый ОписаниеОповещения("ПередПомещениемФайла", ЭтотОбъект);
	Попытка
		ОписаниеПомещенногоФайла = Ждать ПоместитьФайлНаСерверАсинх(ОХодеПомещенияФайла, ПередПомещениемФайла,,, УникальныйИдентификатор);
	Исключение
		Ждать ПредупреждениеАсинх(НСтр("ru='Ошибка помещения файла на сервер'", "ru"));
		Возврат;
	КонецПопытки;
	Если Не ОписаниеПомещенногоФайла = Неопределено Тогда
		НовыйОбъект = Объект.Ссылка.Пустая();
		Объект.ИмяФайла = ОписаниеПомещенногоФайла.СсылкаНаФайл.Имя;
		Если Не ЗначениеЗаполнено(Объект.Наименование) Тогда
#Если МобильныйКлиент Тогда
			Объект.Наименование = ОписаниеПомещенногоФайла.СсылкаНаФайл.Файл.ПолучитьПредставлениеФайлаБиблиотекиМобильногоУстройства();
#Иначе
			Объект.Наименование = ПолучитьИмяФайла(ОписаниеПомещенногоФайла.СсылкаНаФайл.Имя);
#КонецЕсли  
		КонецЕсли;
		ПоместитьФайлОбъекта(ОписаниеПомещенногоФайла.Адрес);
		Если НовыйОбъект Тогда
			ОтобразитьИзменениеДанных(Объект.Ссылка, ВидИзмененияДанных.Добавление);
		Иначе
			ОтобразитьИзменениеДанных(Объект.Ссылка, ВидИзмененияДанных.Изменение);
		КонецЕсли;
	КонецЕсли;
	ПодключитьОбработчикОжидания("СкрытьИндикаторПрогресса", 1, Истина);
КонецПроцедуры

&НаКлиенте
Процедура СкрытьИндикаторПрогресса() Экспорт        		
	Элементы.ИндикаторПрогресса.Видимость = Ложь;
КонецПроцедуры

&НаКлиенте
Процедура ПрочитатьФайлИСохранитьНаДиск(Команда)
	ВыполнитьПрочитатьФайлИСохранитьНаДиск();
КонецПроцедуры
	
&НаКлиенте
Асинх Процедура ВыполнитьПрочитатьФайлИСохранитьНаДиск()
	Если Объект.Ссылка.Пустая() Тогда
		Ждать ПредупреждениеАсинх(НСтр("ru = 'Данные не записаны'", "ru"));
		Возврат;
	КонецЕсли;
	Если ПустаяСтрока(Объект.ИмяФайла) Тогда
		Ждать ПредупреждениеАсинх(НСтр("ru = 'Имя не задано'", "ru"));
		Возврат;
	КонецЕсли;
	Адрес = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "ДанныеФайла");
	ПутьКФайлу = СокрЛП(ПутьКРабочемуКаталогу);
	Если Не СтрЗаканчиваетсяНа(ПутьКФайлу, ПолучитьРазделительПутиКлиента()) Тогда
		ПутьКФайлу = ПутьКФайлу + ПолучитьРазделительПутиКлиента();
	КонецЕсли;
	ПолученныеФайлы = Неопределено;
	Попытка
		ПолученныеФайлы = Ждать ПолучитьФайлССервераАсинх(Адрес, ПутьКФайлу + Объект.ИмяФайла);
	Исключение
	КонецПопытки;
	Если Не ПолученныеФайлы = Неопределено Тогда
		ТекстСообщения = НСтр("ru='Файл %ПутьИмяФайла% получен'", "ru");
	Иначе
		ТекстСообщения = НСтр("ru='Ошибка получения файла %ПутьИмяФайла%.%СимволыПС%Проверьте наличие каталога.'", "ru");
	КонецЕсли;
	ТекстСообщения = СтрЗаменить(ТекстСообщения, "%ПутьИмяФайла%", ПутьКФайлу + Объект.ИмяФайла);
	ТекстСообщения = СтрЗаменить(ТекстСообщения, "%СимволыПС%", Символы.ПС);
	Ждать ПредупреждениеАсинх(ТекстСообщения);
КонецПроцедуры

#Если МобильныйКлиент Тогда 
	
&НаКлиенте
Процедура ПоместитьМультимедиа(ДанныеМультимедиа)
	
	Если ДанныеМультимедиа <> Неопределено Тогда
		НовыйОбъект = Объект.Ссылка.Пустая();
		АдресВременногоХранилища = ПоместитьВоВременноеХранилище(ДанныеМультимедиа.ПолучитьДвоичныеДанные(), УникальныйИдентификатор);
		ТипСодержимого = ДанныеМультимедиа.ТипСодержимого;
		Номер = Найти(ТипСодержимого, "/");
		Если Номер > 0 Тогда
			ТипСодержимого = Лев(ТипСодержимого, Номер - 1);
		КонецЕсли;
		Объект.Наименование = ТипСодержимого + " " + Строка(ТекущаяДата());
		Объект.ИмяФайла = СтрЗаменить(Строка(ТекущаяДата()), ":", "_") + "." + ДанныеМультимедиа.РасширениеФайла;
		ПоместитьФайлОбъекта(АдресВременногоХранилища);
		Если НовыйОбъект Тогда
			ОтобразитьИзменениеДанных(Объект.Ссылка, ВидИзмененияДанных.Добавление);
		Иначе
			ОтобразитьИзменениеДанных(Объект.Ссылка, ВидИзмененияДанных.Изменение);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры
	
&НаКлиенте
Процедура СделатьАудиозапись(Команда)
	
	ДанныеМультимедиа = СредстваМультимедиа.СделатьАудиозапись();
	ПоместитьМультимедиа(ДанныеМультимедиа);
	
КонецПроцедуры

&НаКлиенте
Процедура СделатьВидеозапись(Команда)
	
	ДанныеМультимедиа = СредстваМультимедиа.СделатьВидеозапись();
	ПоместитьМультимедиа(ДанныеМультимедиа);
	
КонецПроцедуры

&НаКлиенте
Процедура СделатьФотоснимок(Команда)
	
	ОтметкаДаты = Неопределено;
	ТекстОтметки = Неопределено;
	ПолучитьДанныеОтметки(ОтметкаДаты, ТекстОтметки);
	Отметка = Новый ОтметкаНаФотоснимке(ОтметкаДаты, "ДФ='dd.MM.yyyy ЧЧ:мм'", ТекстОтметки);
	ДанныеМультимедиа = СредстваМультимедиа.СделатьФотоснимок(,,,,,Отметка);
	ПоместитьМультимедиа(ДанныеМультимедиа);
	
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьСохраненноеАудиоИЗаписать(Команда)
	ТипКаталога = ТипКаталогаБиблиотекиМобильногоУстройства.Аудио;
	ВыполнитьДобавитьСохраненноеАудиоВидеоФотоИЗаписат(ТипКаталога);
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьСохраненноеВидеоИЗаписать(Команда)
	ТипКаталога = ТипКаталогаБиблиотекиМобильногоУстройства.Видео;
	ВыполнитьДобавитьСохраненноеАудиоВидеоФотоИЗаписат(ТипКаталога);
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьСохраненноеФотоИЗаписать(Команда)
	ТипКаталога = ТипКаталогаБиблиотекиМобильногоУстройства.Картинки;
	ВыполнитьДобавитьСохраненноеАудиоВидеоФотоИЗаписат(ТипКаталога);
КонецПроцедуры

&НаКлиенте
Асинх Процедура ВыполнитьДобавитьСохраненноеАудиоВидеоФотоИЗаписат(ТипКаталога)
	Перем ВыбранноеИмя;
	Каталог = Ждать КаталогБиблиотекиМобильногоУстройстваАсинх(ТипКаталога);
	Попытка
		ПомещенныеФайлы = Ждать ПоместитьФайлНаСерверАсинх(,,,, УникальныйИдентификатор);
	Исключение
		Ждать ПредупреждениеАсинх(НСтр("ru='Ошибка помещения файлов'", "ru"));
	КонецПопытки;
	Если ПомещенныеФайлы <> Неопределено Тогда
#Если МобильныйКлиент Тогда 
		Файл = Новый Файл(ПомещенныеФайлы[0].СсылкаНаФайл.Имя);
		ВыбранноеИмя = Файл.ПолучитьПредставлениеФайлаБиблиотекиМобильногоУстройства();
#КонецЕсли
		Объект.ИмяФайла = ВыбранноеИмя;
		ПоместитьФайлОбъекта(ПомещенныеФайлы[0].Адрес);
	Иначе
		Сообщение = Новый СообщениеПользователю();
		Сообщение.Текст = НСтр("ru = 'Файлы не загружены'", "ru");
		Сообщение.Сообщить();
	КонецЕсли;
КонецПроцедуры

#КонецЕсли

//////////////////////////////////////////////////////////////////////////////// 
// ОБРАБОТЧИКИ Команд криптографии 
// 

&НаКлиенте
Процедура Подписать(Команда)  
	// Получает на клиента
	// Подписывает
	// Помещает на сервер файл и подпись
	ВыполнитьПодписать();
КонецПроцедуры

&НаКлиенте
Асинх Процедура ВыполнитьПодписать()
	Попытка
		РезультатПодключенияРасширенияРаботыСКриптографией = Ждать ПодключитьРасширениеРаботыСКриптографиейАсинх();
	Исключение
		Ждать ПредупреждениеАсинх(НСтр("ru='Ошибка подключения расширения работы с криптографией'", "ru"));
		Возврат;
	КонецПопытки;
	Если Не РезультатПодключенияРасширенияРаботыСКриптографией Тогда
		Сообщить(НСтр("ru='Для требуемой операции необходимо установить расширение работы с криптографией'", "ru"));
		Возврат;
	КонецЕсли;
	Данные = ПолучитьДанныеФайла();
	Если Данные.Количество() = 0 Тогда
		Ждать ПредупреждениеАсинх(НСтр("ru = 'Нет данных файла!!!'", "ru"), 10);
		Возврат;
	КонецЕсли;
	ФайлДвоичныеДанные = Данные[0];
	Данные.Удалить(0);
	ПараметрыВыбораСертификатов = Новый СписокЗначений;
	ПараметрыВыбораСертификатов.Добавить(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты);
	Контекст = Новый Структура("Данные, ФайлДвоичныеДанные", Данные, ФайлДвоичныеДанные);
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("МножественныйВыбор", Истина);
	ФормаСпискаСертификатов = ПолучитьФорму("Справочник.ХранимыеФайлы.Форма.СписокСертификатов", ПараметрыФормы);
	ФормаСпискаСертификатов.Установка(ПараметрыВыбораСертификатов);
	ФормаСпискаСертификатов.ОписаниеОповещенияОЗакрытии =
		Новый ОписаниеОповещения("РезультатВыбораСертификатовДляПодписания", ЭтотОбъект, Контекст);
	ФормаСпискаСертификатов.Открыть();
КонецПроцедуры

&НаКлиенте
Процедура РезультатВыбораСертификатовДляПодписания(Результат, Контекст) Экспорт
	Если Результат = КодВозвратаДиалога.Отмена Тогда 
		Возврат;
	КонецЕсли;
	МенеджерКриптографии = Новый МенеджерКриптографии();
	Контекст2 = Новый Структура(
		"МенеджерКриптографии, ФайлДвоичныеДанные, Сертификат, Данные", 
		МенеджерКриптографии, Контекст.ФайлДвоичныеДанные, Результат, Контекст.Данные);
	ПродолжитьПодписаниеСертификатов(Контекст2);
КонецПроцедуры

&НаКлиенте
Асинх Процедура ПродолжитьПодписаниеСертификатов(Контекст2)
	МенеджерКриптографии = Контекст2.МенеджерКриптографии;
	Попытка
		Ждать МенеджерКриптографии.ИнициализироватьАсинх("", "", 75);
	Исключение
		Сообщить(НСтр("ru='Ошибка инициализации менеджера криптографии'", "ru"));
		Возврат;
	КонецПопытки;
	Контекст2.Вставить("ПодписиПолучены", Новый Массив());
	УстановитьСледующиеПодписи(, Контекст2);
КонецПроцедуры

&НаКлиенте
Асинх Процедура УстановитьСледующиеПодписи(СертификатыПодписи, Контекст)
	Если СертификатыПодписи  <> Неопределено Тогда
		Для Каждого СертификатПодписи Из СертификатыПодписи Цикл
			Если Контекст.Сертификат = СертификатПодписи Тогда 
				Ждать ПредупреждениеАсинх(
					НСтр("ru = 'Этим сертификатом файл уже подписан'", "ru"),
					10);
				Возврат;
			КонецЕсли;
		КонецЦикла;
		Контекст.ПодписиПолучены.Добавить(Истина);
	КонецЕсли;
	Если Контекст.ПодписиПолучены.Количество() = Контекст.Данные.Количество() Тогда
		// подписываем
		Контекст2 = Новый Структура(
			"МенеджерКриптографии, ФайлДвоичныеДанные, Сертификат, Данные", 
			Контекст.МенеджерКриптографии, Контекст.ФайлДвоичныеДанные, Контекст.Сертификат, Контекст.Данные);
		ВводПароля(Контекст.МенеджерКриптографии, "ПодписатьЗавершение2", Контекст2);	
		Возврат;
	КонецЕсли;
	ТекущиеДанные = Контекст.Данные[Контекст.ПодписиПолучены.Количество()];			
	СертификатыПодписи = Ждать Контекст.МенеджерКриптографии.ПолучитьСертификатыИзПодписиАсинх(ТекущиеДанные);
	УстановитьСледующиеПодписи(СертификатыПодписи, Контекст);
КонецПроцедуры

&НаКлиенте
Процедура ПодписатьЗавершение2(Результат, Контекст) Экспорт
	Если Результат = КодВозвратаДиалога.ОК Тогда
		ЗавершитьПодписать(Контекст);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Асинх Процедура ЗавершитьПодписать(Контекст)
	МенеджерКриптографии = Контекст.МенеджерКриптографии;
	ФайлДвоичныеДанные = Контекст.ФайлДвоичныеДанные;
	Сертификат = Контекст.Сертификат;
	Попытка
		ПодписанныеДанные = Ждать МенеджерКриптографии.ПодписатьАсинх(ФайлДвоичныеДанные, Сертификат);
	Исключение
		Ждать ПредупреждениеАсинх(НСтр("ru='Ошибка подписания файла'", "ru"));
		Возврат;
	КонецПопытки;
	Контекст.Данные.Добавить(ПодписанныеДанные);
	// Сохраняем на сервере, использование пустой строки избавляет
	// от необходимости передавать обратно файл на сервер - он не менялся
	ЗаписатьДанныеФайла("", Контекст.Данные);
	ОтобразитьИзменениеДанных(Объект.Ссылка, ВидИзмененияДанных.Изменение);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьПодпись(Команда)
	ВыполнитьПроверкуПодписи();
КонецПроцедуры

&НаКлиенте
Асинх Процедура ВыполнитьПроверкуПодписи()
	// Подписи проверяем на сервере
	Если ПроверитьПодписьНаСервере() Тогда 
		Сообщение = НСтр("ru = 'Успешное завершение проверки ЭЦП'", "ru");
		Ждать ПредупреждениеАсинх(
			Сообщение, 
			3);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПоместитьЗашифрованныйНаСервер(Команда)
	ВыполнитьПомещениеЗашифрованныйНаСервер();
КонецПроцедуры

&НаКлиенте
Асинх Процедура ВыполнитьПомещениеЗашифрованныйНаСервер()
	Попытка
		РезультатПодключенияРасширенияРаботыСКриптографией = Ждать ПодключитьРасширениеРаботыСКриптографиейАсинх();
	Исключение
		Ждать ПредупреждениеАсинх(НСтр("ru='Ошибка подключения расширения работы с криптографией'", "ru"));
		Возврат;
	КонецПопытки;
	Если Не РезультатПодключенияРасширенияРаботыСКриптографией Тогда
		Сообщить(НСтр("ru='Для требуемой операции необходимо установить расширение работы с криптографией'", "ru"));
		Возврат;
	КонецЕсли;
	МенеджерКриптографии = Новый МенеджерКриптографии();
	Попытка
		Ждать МенеджерКриптографии.ИнициализироватьАсинх("", "", 75);
	Исключение
		Сообщить(НСтр("ru='Ошибка инициализации менеджера криптографии'", "ru"));
		Возврат;
	КонецПопытки;
	Контекст = Новый Структура(
		"МенеджерКриптографии, НовыйОбъект, ИсходныеДанныеДляШифрования",
		МенеджерКриптографии, Объект.Ссылка.Пустая(), Неопределено);
	РезультатПодключенияРасширенияРаботыСФайлами = Ждать ПодключитьРасширениеРаботыСФайламиАсинх();
	// выбор файла на диске, который нужно зашифровать и сохранить на сервере
	Если Не РезультатПодключенияРасширенияРаботыСФайлами Тогда
		// если не подключено расширение работы с файлами, операция выполняется
		// неоптимально, увеличивается трафик с сервером и снижается защищенность
		Попытка
			ОписаниеПомещенногоФайлаНаСервер = Ждать ПоместитьФайлНаСерверАсинх(,,,, УникальныйИдентификатор);
		Исключение
			Сообщить(НСтр("ru='Ошибка помещения файла на сервер'", "ru"));
		КонецПопытки;
		ИмяВыбранногоФайла = ОписаниеПомещенногоФайлаНаСервер.СсылкаНаФайл.Имя;
		Контекст.ИсходныеДанныеДляШифрования = ПолучитьИзВременногоХранилища(ОписаниеПомещенногоФайлаНаСервер.Адрес);
	Иначе
		Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
		МассивИменВыбранныхФайлов = Ждать Диалог.ВыбратьАсинх();
		Если МассивИменВыбранныхФайлов = Неопределено Тогда
			Возврат;
		КонецЕсли;
		ИмяВыбранногоФайла = МассивИменВыбранныхФайлов[0];
		Контекст.ИсходныеДанныеДляШифрования = ИмяВыбранногоФайла;
	КонецЕсли;
	ЧастиИмени = СтрРазделить(ИмяВыбранногоФайла, ПолучитьРазделительПути());
	Если ЧастиИмени.Количество() <= 0 Тогда 
		Возврат;
	КонецЕсли;
	Объект.ИмяФайла = ЧастиИмени[ЧастиИмени.Количество() - 1];
	// Формируем список сертификатов, которыми можно будет файл расшифровать
	ПараметрыВыбораСертификатов = Новый СписокЗначений;
	ПараметрыВыбораСертификатов.Добавить(ТипХранилищаСертификатовКриптографии.СертификатыПолучателей);
	ПараметрыВыбораСертификатов.Добавить(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты);
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("МножественныйВыбор", Истина);
	ФормаСпискаСертификатов = ПолучитьФорму("Справочник.ХранимыеФайлы.Форма.СписокСертификатов", ПараметрыФормы);
	ФормаСпискаСертификатов.Установка(ПараметрыВыбораСертификатов);
	ФормаСпискаСертификатов.ОписаниеОповещенияОЗакрытии =
		Новый ОписаниеОповещения("РезультатВыбораСертификатовДляПомещенияЗашифрованныйНаСервер", ЭтотОбъект, Контекст);
	ФормаСпискаСертификатов.Открыть();
КонецПроцедуры

&НаКлиенте
Процедура РезультатВыбораСертификатовДляПомещенияЗашифрованныйНаСервер(Результат, Контекст) Экспорт
	Если Результат = КодВозвратаДиалога.Отмена Тогда 
		Возврат;
	КонецЕсли;
	Сертификаты = Результат;
	Если Сертификаты = Неопределено Или Сертификаты.Количество() = 0 Тогда 
		Возврат;
	КонецЕсли;
	МенеджерКриптографии = Контекст.МенеджерКриптографии;
	ИсходныеДанныеДляШифрования = Контекст.ИсходныеДанныеДляШифрования;
	НовыйОбъект = Контекст.НовыйОбъект;
	ПродолжитьПомещениеЗашифрованныйНаСервер(Сертификаты, МенеджерКриптографии, ИсходныеДанныеДляШифрования, НовыйОбъект);
КонецПроцедуры

&НаКлиенте
Асинх Процедура ПродолжитьПомещениеЗашифрованныйНаСервер(Сертификаты, МенеджерКриптографии, ИсходныеДанныеДляШифрования, НовыйОбъект)
	Попытка
		ПодписанныеДанные = Ждать МенеджерКриптографии.ЗашифроватьАсинх(ИсходныеДанныеДляШифрования, Сертификаты);
	Исключение
		Ждать ПредупреждениеАсинх(НСтр("ru='Ошибка шифрования данных'", "ru"));
		Возврат;
	КонецПопытки;
	Объект.Зашифрован = Истина;
	// Сохраняем на сервере
	ЗаписатьДанныеФайла(ПодписанныеДанные, Новый Массив);
	Если НовыйОбъект Тогда
		ОтобразитьИзменениеДанных(Объект.Ссылка, ВидИзмененияДанных.Добавление);
	Иначе
		ОтобразитьИзменениеДанных(Объект.Ссылка, ВидИзмененияДанных.Изменение);
	КонецЕсли;
КонецПроцедуры

&НаСервере
Функция ЗашифроватьНаСервере(ДанныеСертификатов, ТекстОшибки)
	Сертификаты = Новый Массив();
	Для Каждого ДанныеСертификата Из ДанныеСертификатов Цикл
		Сертификаты.Добавить(Новый СертификатКриптографии(ДанныеСертификата));
	КонецЦикла;
	
	МенеджерКриптографии = Новый МенеджерКриптографии("", "", 75);
	Данные = ПолучитьДанныеФайла();
	Если Данные.Количество() = 0 Тогда
		ТекстОшибки = НСтр("ru = 'Нет данных файла!!!'", "ru");
		Возврат Ложь;
	КонецЕсли;
	ФайлДвоичныеДанные = Данные[0];
	Данные.Удалить(0);
	
	// шифруем
	ЗашифрованныйДвоичныеДанные = МенеджерКриптографии.Зашифровать(ФайлДвоичныеДанные, Сертификаты);

	// Сохраняем на сервере
	Объект.Зашифрован = Истина;
	ЗаписатьДанныеФайла(ЗашифрованныйДвоичныеДанные, Данные);
	Возврат Истина;
КонецФункции

&НаКлиенте
Процедура Зашифровать(Команда)
	ВыполнитьЗашифровать();
КонецПроцедуры

&НаКлиенте
Асинх Процедура ВыполнитьЗашифровать()
	Попытка
		РезультатПодключенияРасширенияРаботыСКриптографией = Ждать ПодключитьРасширениеРаботыСКриптографиейАсинх();
	Исключение
		Ждать ПредупреждениеАсинх(НСтр("ru='Ошибка подключения расширения работы с криптографией'", "ru"));
		Возврат;
	КонецПопытки;
	Если Не РезультатПодключенияРасширенияРаботыСКриптографией Тогда
		Сообщить(НСтр("ru='Для требуемой операции необходимо установить расширение работы с криптографией'", "ru"));
		Возврат;
	КонецЕсли;
	Если Объект.Зашифрован Тогда
		Сообщить(НСтр("ru = 'Файл уже зашифрован'", "ru"));
		Возврат;
	КонецЕсли;
	
	Если Объект.Подписан Тогда
		Сообщить(НСтр("ru = 'Файл подписан, операция шифрования запрещена'", "ru"));
		Возврат;
	КонецЕсли;
	
	// Формируем список сертификатов, которыми можно будет файл расшифровать
	ПараметрыФормы = Новый СписокЗначений;
	ПараметрыФормы.Добавить(ТипХранилищаСертификатовКриптографии.СертификатыПолучателей);
	ПараметрыФормы.Добавить(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты);
	ПолучитьСписокСертификатов(ПараметрыФормы, Истина, "ЗашифроватьЗавершение");
КонецПроцедуры

&НаКлиенте
Процедура ЗашифроватьЗавершение(Результат, Контекст) Экспорт

	Если Результат = КодВозвратаДиалога.Отмена Тогда 
		Возврат;
	КонецЕсли;
	
	Сертификаты = Результат;
	
	Если Сертификаты = Неопределено Или Сертификаты.Количество() = 0 Тогда 
		Возврат;
	КонецЕсли;
	
	НовыйОбъект = Объект.Ссылка.Пустая();
	
	Контекст = Новый Структура(
		"НовыйОбъект, Сертификаты, ДанныеСертификатов",
		НовыйОбъект, Сертификаты, Новый Массив());
	ВыгрузитьСледующийСертификатДляШифрования(, Контекст);

КонецПроцедуры

&НаКлиенте
Асинх Процедура ВыгрузитьСледующийСертификатДляШифрования(ВыгруженныеДанные, Контекст)
	Перем ТекстОшибки;
	Если ВыгруженныеДанные <> Неопределено Тогда
		Контекст.ДанныеСертификатов.Добавить(ВыгруженныеДанные);
	КонецЕсли;
	Если Контекст.ДанныеСертификатов.Количество() = Контекст.Сертификаты.Количество() Тогда
		Результат = ЗашифроватьНаСервере(Контекст.ДанныеСертификатов, ТекстОшибки);
		Если Не Результат Тогда
			Сообщить(ТекстОшибки);
			Возврат;
		КонецЕсли;
		Если Контекст.НовыйОбъект Тогда
			ОтобразитьИзменениеДанных(Объект.Ссылка, ВидИзмененияДанных.Добавление);
		Иначе
			ОтобразитьИзменениеДанных(Объект.Ссылка, ВидИзмененияДанных.Изменение);
		КонецЕсли;
		Возврат;
	КонецЕсли;
	ТекущийСертификат = Контекст.Сертификаты[Контекст.ДанныеСертификатов.Количество()];			
	ВыгруженныеДанные = Ждать ТекущийСертификат.ВыгрузитьАсинх();
	ВыгрузитьСледующийСертификатДляШифрования(ВыгруженныеДанные, Контекст);
КонецПроцедуры	

&НаКлиенте
Процедура ПолучитьСРасшифровкой(Команда)
	// Получить на клиента
	// Расшифровать
	// Если двоичные данные, то передать на сервер
	// Поместить в файл
	Если ТипЗнч(Объект.Владелец) <> Тип("СправочникСсылка.Контрагенты") Тогда 
		Сообщение = НСтр("ru = 'Расшифровать возможно только файлы контрагентов'", "ru");
		Сообщить(Сообщение);
		Возврат;
	КонецЕсли;
	ВыполнитьПолучитьСРасшифровкой();
КонецПроцедуры

&НаКлиенте
Асинх Процедура ВыполнитьПолучитьСРасшифровкой()
	Попытка
		РезультатПодключенияРасширенияРаботыСКриптографией = Ждать ПодключитьРасширениеРаботыСКриптографиейАсинх();
	Исключение
		Ждать ПредупреждениеАсинх(НСтр("ru='Ошибка подключения расширения работы с криптографией'", "ru"));
		Возврат;
	КонецПопытки;
	Если Не РезультатПодключенияРасширенияРаботыСКриптографией Тогда
		Сообщить(НСтр("ru='Для требуемой операции необходимо установить расширение работы с криптографией'", "ru"));
		Возврат;
	КонецЕсли;
	Данные = ПолучитьДанныеФайла();
	Если Данные.Количество() = 0 Тогда
		Сообщить(НСтр("ru = 'Нет данных файла!!!'", "ru"));
		Возврат;
	КонецЕсли;
	ФайлДвоичныеДанные = Данные[0];
	Данные.Удалить(0);
	МенеджерКриптографии = Новый МенеджерКриптографии();
	Контекст = Новый Структура(
		"МенеджерКриптографии, ФайлДвоичныеДанные",
		МенеджерКриптографии, ФайлДвоичныеДанные);
	Попытка
		Ждать МенеджерКриптографии.ИнициализироватьАсинх("", "", 75);
	Исключение
		Сообщить(НСтр("ru='Ошибка инициализации менеджера криптографии'", "ru"));
		Возврат;
	КонецПопытки;
	ВводПароля(МенеджерКриптографии, "ПолучитьСРасшифровкойЗавершение", Контекст);
КонецПроцедуры

&НаКлиенте
Процедура ПолучитьСРасшифровкойЗавершение(Результат, Контекст) Экспорт
	Если Результат <> КодВозвратаДиалога.ОК Тогда
		Возврат;
	КонецЕсли;
	ПродолжитьПолучитьСРасшифровкой(Контекст);
КонецПроцедуры

&НаКлиенте
Асинх Процедура ПродолжитьПолучитьСРасшифровкой(Контекст)
	РезультатПодключенияРасширенияРаботыСФайлами = Ждать ПодключитьРасширениеРаботыСФайламиАсинх();
	МенеджерКриптографии = Контекст.МенеджерКриптографии;
	ФайлДвоичныеДанные = Контекст.ФайлДвоичныеДанные;
	Если Не РезультатПодключенияРасширенияРаботыСФайлами Тогда
		Попытка
			Ждать МенеджерКриптографии.РасшифроватьАсинх(ФайлДвоичныеДанные);
		Исключение
			Сообщить(НСтр("ru='Ошибка расшифровки данных'", "ru"));
		КонецПопытки;
		АдресВоВременномХранилище = ПоместитьВоВременноеХранилище(ЭтотОбъект, УникальныйИдентификатор);
		ИмяФайла = Объект.ИмяФайла;
		ПолучитьФайл(АдресВоВременномХранилище, ИмяФайла, Истина);	
	Иначе
		Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
		МассивИменВыбранныхФайлов = Ждать Диалог.ВыбратьАсинх();
		Если МассивИменВыбранныхФайлов = Неопределено Тогда
			Возврат;
		КонецЕсли;
		ИмяВыбранногоФайла = МассивИменВыбранныхФайлов[0];
		Попытка
			Ждать МенеджерКриптографии.РасшифроватьАсинх(ФайлДвоичныеДанные);
		Исключение
			Сообщить(НСтр("ru='Ошибка расшифровки данных'", "ru"));
		КонецПопытки;
	КонецЕсли;
КонецПроцедуры

//////////////////////////////////////////////////////////////////////////////// 
// ПРОЦЕДУРЫ И ФУНКЦИИ 
// 

// процедура проверяет подписи
// - возращает Истина, если все подписи прошли проверку
&НаСервере
Функция ПроверитьПодписьНаСервере()
	Данные = ПолучитьДанныеФайла();
	Если Данные.Количество() = 0 Тогда
		Сообщить(НСтр("ru = 'Нет данных файла!!!'", "ru"));
		Возврат Ложь;
	КонецЕсли;
	ФайлДвоичныеДанные = Данные[0];
	Данные.Удалить(0);
	Если Данные.Количество() = 0 Тогда
		Сообщение = НСтр("ru = 'Файл никем не подписан'", "ru");
		Сообщить(Сообщение);
		Возврат Ложь;
	КонецЕсли;
	МенеджерКриптографии = Новый МенеджерКриптографии("", "", 75);
	Для Каждого ЭЦПДвоичныеДанные Из Данные Цикл
		МенеджерКриптографии.ПроверитьПодпись(ФайлДвоичныеДанные, ЭЦПДвоичныеДанные);
	КонецЦикла;
	Возврат Истина;
КонецФункции

// процедура сохраняет на сервере файл, и, при наличии, файлы ЭЦП
&НаСервере
Процедура ЗаписатьДанныеФайла(ФайлДвоичныеДанные, ЭЦПДвоичныеДанные)
	ЭлементСправочника = РеквизитФормыВЗначение("Объект");
	// ДанныеФайла меняем, только если переданы двоичные ланные
	Если ТипЗнч(ФайлДвоичныеДанные) = Тип("ДвоичныеДанные") Тогда
		ЭлементСправочника.ДанныеФайла = Новый ХранилищеЗначения(ФайлДвоичныеДанные, Новый СжатиеДанных());
	КонецЕсли;

	ЭлементСправочника.Подпись = Новый ХранилищеЗначения(ЭЦПДвоичныеДанные, Новый СжатиеДанных());
	
	ЭлементСправочника.Записать();
	Модифицированность = Ложь;
	ЗначениеВРеквизитФормы(ЭлементСправочника, "Объект");     
	
КонецПроцедуры	

// процедура получает с сервера в виде массива двоичных данных файлы, первым идет
// файл, затем, при наличии, файлы ЭЦП
&НаСервере
Функция ПолучитьДанныеФайла()
	Данные = Новый Массив;
	ЭлементСправочника = РеквизитФормыВЗначение("Объект");
	ФайлДвоичныеДанные = ЭлементСправочника.ДанныеФайла.Получить();
	Если ТипЗнч(ФайлДвоичныеДанные) = Тип("ДвоичныеДанные") Тогда
		Данные.Добавить(ФайлДвоичныеДанные);
		ФайлыЭЦП = ЭлементСправочника.Подпись.Получить();
		Если ТипЗнч(ФайлыЭЦП) = Тип("Массив") Тогда
			Для Каждого ФайлЭЦП Из ФайлыЭЦП Цикл
				Если ТипЗнч(ФайлЭЦП) = Тип("ДвоичныеДанные") Тогда
					Данные.Добавить(ФайлЭЦП);
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	Возврат Данные;
КонецФункции
	
// Формирование (интерактивное) списка сертификатов криптографии
// ПараметрыВыбора - список типов хранилищ, сертификаты которых могут участвовать в выборе
// МножественныйВыбор
&НаКлиенте
Процедура ПолучитьСписокСертификатов(ПараметрыВыбора, МножественныйВыбор, ИмяПроцедурыЗавершения, Контекст = Неопределено)
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("МножественныйВыбор", МножественныйВыбор);
	ФормаСпискаСертификатов = ПолучитьФорму("Справочник.ХранимыеФайлы.Форма.СписокСертификатов", ПараметрыФормы);
	ФормаСпискаСертификатов.Установка(ПараметрыВыбора);
	ФормаСпискаСертификатов.ОписаниеОповещенияОЗакрытии =
		Новый ОписаниеОповещения(ИмяПроцедурыЗавершения, ЭтотОбъект, Контекст);
	ФормаСпискаСертификатов.Открыть();
КонецПроцедуры

// Процедура извлекает данные объекта из временного хранилища, 
// производит модификацию элемента справочника и записывает его.
// 
// Параметры: 
//  АдресВременногоХранилища – Строка – адрес временного хранилища. 
// 
// Возвращаемое значение: 
//  Нет.
&НаСервере
Процедура ПоместитьФайлОбъекта(АдресВременногоХранилища)
	ЭлементСправочника = РеквизитФормыВЗначение("Объект");
	ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВременногоХранилища);
	ЭлементСправочника.ДанныеФайла = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных());
	Файл = Новый Файл(ЭлементСправочника.ИмяФайла);
	ЭлементСправочника.ИмяФайла = Файл.Имя;
	ЭлементСправочника.Подпись = Новый ХранилищеЗначения(Неопределено, Новый СжатиеДанных());
	ЭлементСправочника.Зашифрован = Ложь;
	ЭлементСправочника.Подписан = Ложь;
	ЭлементСправочника.Записать();
	Модифицированность = Ложь;
	УдалитьИзВременногоХранилища(АдресВременногоХранилища);
	ЗначениеВРеквизитФормы(ЭлементСправочника, "Объект");     
КонецПроцедуры

// интерактивный ввод пароля доступа к закрытому ключу сертификата криптографии
// возвращает введенный пароль в параметре вызова Пароль
// возращает Истина, если пароль введен
&НаКлиенте
Процедура ВводПароля(МенеджерСертификатов, ИмяПроцедурыЗавершения, Контекст = Неопределено)
	Вернуть = Ложь;
	ФормаПароля = ПолучитьФорму("Справочник.ХранимыеФайлы.Форма.ФормаПароля");
	ФормаПароля.МенеджерСертификатов = МенеджерСертификатов;
	ФормаПароля.ОписаниеОповещенияОЗакрытии =
		Новый ОписаниеОповещения(ИмяПроцедурыЗавершения, ЭтотОбъект, Контекст);
	ФормаПароля.Открыть();
КонецПроцедуры

// Функция возвращает имя файла из полного пути
// 
// Параметры: 
//  ПолныйПутьКФайлу – Строка – полный путь к файлу. 
// 
// Возвращаемое значение: 
//  Строка - имя файла.
&НаКлиенте
Функция ПолучитьИмяФайла(ПолныйПутьКФайлу)
	
	Если ПолныйПутьКФайлу = "" Тогда
		Возврат "";
	КонецЕсли;
	
	ПозицияРазделителя = СтрНайти(ПолныйПутьКФайлу, 
		ПолучитьРазделительПути(), 
		НаправлениеПоиска.СКонца);
		
	Если ПозицияРазделителя = 0 Тогда
		Возврат ПолныйПутьКФайлу;
	КонецЕсли;
	
	Возврат Прав(ПолныйПутьКФайлу, 
		СтрДлина(ПолныйПутьКФайлу) - ПозицияРазделителя);
	
КонецФункции
